<template>
  <y-dialog @open="open" @close="emit('close')" width="1000px" append-to-body>
    <el-form
      ref="addRef"
      :model="form"
      :rules="rules"
      size="default"
      label-width="120px"
    >
      <el-row>
        <el-col :span="24">
          <el-form-item label="任务名称" prop="name">
            <el-input v-model="form.name" placeholder="请输入任务名称" />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="12">
          <el-form-item label="任务类型" prop="type">
            <y-select
              v-model="form.type"
              placeholder="请选择任务类型"
              :options="tms_job_type"
              @change="handleTypeChange"
            />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="负责人" prop="owner">
            <y-select
              v-model="form.owner"
              placeholder="请选择负责人"
              :optionsFunc="listUser"
            />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="12">
          <el-form-item label="执行节点" prop="nodes">
            <y-select
              v-model="form.nodes"
              placeholder="请选择执行节点"
              :optionsFunc="listNode"
              multiple
            />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="测试环境" prop="env">
            <y-select
              v-model="form.env"
              placeholder="请选择测试环境"
              :optionsFunc="listEnv"
            />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="12">
          <el-form-item label="所属产品" prop="product">
            <y-select
              v-model="form.product"
              placeholder="请选择所属产品"
              :optionsFunc="listProduct"
              @change="changeProductOptions"
            />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="测试计划" prop="testplan">
            <y-select
              v-model="form.testplan"
              placeholder="请选择测试计划"
              :optionsFunc="listTestPlan"
              :optionsParams="queryParams"
              @change="changeTestPlanOptions"
            />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="24">
          <el-form-item label="测试用例" prop="tcs" style="font-weight: bold">
            <el-checkbox
              v-model="caseExpand"
              @change="handleCheckedTreeExpand($event)"
              >展开/折叠
            </el-checkbox>
            <el-checkbox
              v-model="caseNodeAll"
              @change="handleCheckedTreeNodeAll($event)"
              >全选/全不选
            </el-checkbox>
            <el-checkbox
              v-model="caseCheckStrictly"
              @change="handleCheckedTreeConnect($event)"
              >父子联动
            </el-checkbox>
            <el-tree
              class="tree-border"
              :data="caseOptions"
              show-checkbox
              ref="caseRef"
              node-key="id"
              :check-strictly="!caseCheckStrictly"
              empty-text="加载中，请稍候"
              :props="{ label: 'name', children: 'children' }"
            >
            </el-tree>
          </el-form-item>
        </el-col>
      </el-row>
      <div v-if="automate">
        <el-row>
          <el-col :span="12">
            <el-form-item>
              <template #label>
                <span>
                  <el-tooltip placement="top">
                    <template #content>
                      <div>
                        执行级别影响执行、分析、重试等操作的颗粒度
                        <br />用例级：用例中各个步骤存在关联，可不依赖插件完成自动化执行
                        <br />步骤级：用例中各个步骤不存在关联,
                        需依赖执行插件完成自动化执行
                      </div>
                    </template>
                    <el-icon>
                      <question-filled />
                    </el-icon>
                  </el-tooltip>
                  执行级别
                </span>
              </template>
              <el-radio-group v-model="form.level" @change="handleLevelChange">
                <el-radio value="0">用例级</el-radio>
                <el-radio value="1">步骤级</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item>
              <template #label>
                <span>
                  <el-tooltip placement="top">
                    <template #content>
                      <div>
                        执行策略影响执行的耗时，不影响执行结果，具体如下：
                        <br />执行级别为用例级时，执行策略自动切换为并发执行
                        <br />执行级别为步骤级，执行策略选择并发执行时：用例中各个步骤无需按序执行，并发执行；
                        <br />执行级别为步骤级，执行策略选择顺序执行时：用例中各个步骤需要按序执行，顺序执行。
                      </div>
                    </template>
                    <el-icon>
                      <question-filled />
                    </el-icon>
                  </el-tooltip>
                  执行策略
                </span>
              </template>
              <el-radio-group
                v-model="form.policy"
                :disabled="form.level == '0'"
              >
                <el-radio value="0">并发执行</el-radio>
                <el-radio value="1">顺序执行</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col>
            <el-form-item prop="plugin">
              <template #label>
                <span>
                  <el-tooltip placement="top">
                    <template #content>
                      <div>
                        执行插件是使用既定格式来描述各个执行步骤将进行怎样的操作，以适用任务中所有步骤操作和断言
                        <br />相同，仅参数不同的自动化场景的一个Python脚本，改脚本依赖底层框架，完成相应动作。
                      </div>
                    </template>
                    <el-icon>
                      <question-filled />
                    </el-icon>
                  </el-tooltip>
                  执行插件
                </span>
              </template>
              <y-select
                v-model="form.plugin"
                placeholder="请选择执行插件"
                :optionsFunc="listJobPlugin"
              >
                <template #footer>
                  <el-button text bg size="small" @click="handleJobPlugins">
                    插件管理
                  </el-button>
                </template>
              </y-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row v-if="form.plugin">
          <el-col :span="24">
            <el-form-item prop="params">
              <template #label>
                <span>
                  <el-tooltip placement="top">
                    <template #content>
                      <div>
                        填写示例：{"username":"admin"}
                        <br />参数说明：参数请采用JSON格式
                      </div>
                    </template>
                    <el-icon>
                      <question-filled />
                    </el-icon>
                  </el-tooltip>
                  执行参数
                </span>
              </template>
              <y-code-editor v-model="form.params" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="定时任务" prop="cron">
              <template #label>
                <span>
                  <el-tooltip placement="top">
                    <template #content>
                      <div>
                        Cron表达式是一种强大的定时任务指定方式，广泛用于Unix和类Unix系统中来配置计划任务（crontab）。
                        <br />每个字段都可以包含特定值的列表、值的范围或值的组合，还可以使用通配符。下面是一些字段的示例值和它们所代表的含义：
                        <br />秒（0-59）：可选字段，表示分钟中的第几秒开始执行。
                        <br />分（0-59）：表示小时中的第几分钟开始执行。
                        <br />时（0-23）：表示一天中的第几小时开始执行。
                        <br />日（1-31）：表示月份中的第几天开始执行。
                        <br />月（1-12 或JAN-DEC）：表示年份中的第几月开始执行。
                        <br />周（0-7
                        或SUN-SAT）：表示星期中的第几天开始执行，其中0和7都代表星期日。
                        <br />年（可选，1970-2099）：表示年份中的哪一年开始执行。
                      </div>
                    </template>
                    <el-icon>
                      <question-filled />
                    </el-icon>
                  </el-tooltip>
                  定时任务
                </span>
              </template>
              <el-input v-model="form.cron" placeholder="请输入cron执行表达式">
                <template #append>
                  <el-button type="primary" @click="handleShowCron">
                    生成表达式
                    <i class="el-icon-time el-icon--right"></i>
                  </el-button>
                </template>
              </el-input>
            </el-form-item>
          </el-col>
        </el-row>
      </div>
      <el-row>
        <el-col>
          <el-form-item label="备注" prop="remark">
            <el-input
              v-model="form.remark"
              type="textarea"
              :rows="5"
              placeholder="请输入备注信息"
            />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-col>
          <el-form-item label="标签" prop="tags">
            <y-tag v-model="form.tags" :closable="true" />
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
    <y-dialog
      title="Cron表达式生成器"
      v-model="openCron"
      append-to-body
      destroy-on-close
    >
      <y-crontab
        @submit="submitCronTab"
        @close="openCron = false"
        :expression="expression"
      >
      </y-crontab>
    </y-dialog>

    <template #footer>
      <div class="dialog-footer">
        <el-button type="primary" @click="submit">确定</el-button>
        <el-button type="warning" @click="reset">重置</el-button>
        <el-button @click="emit('close')">取消</el-button>
      </div>
    </template>
  </y-dialog>
</template>

<script setup name="AuJob">
import { listProduct } from "@/api/pms/product";
import { listJobPlugin } from "@/api/tms/job/plugin";
import { listTestPlan } from "@/api/tms/testplan";
import { listEnv } from "@/api/oms/env";
import { listUser } from "@/api/sys/user";
import { listNode } from "@/api/oms/node";
import { treeselect } from "@/api/pms/module";
import YCrontab from "@/components/YCrontab";

const { proxy } = getCurrentInstance();
const { tms_job_type } = proxy.useDict("tms_job_type");

const router = useRouter();
const emit = defineEmits(["submited", "close"]);

const automate = ref(false);
const openCron = ref(false);
const expression = ref("");
const caseOptions = ref([]);
const caseRef = ref(null);
const caseExpand = ref(true);
const caseNodeAll = ref(false);
const caseCheckStrictly = ref(true);
const defaultParams = ref({});

const data = reactive({
  form: {},
  queryParams: {
    product: undefined,
    protocol: undefined,
    showcase: true,
  },
  rules: {
    name: [{ required: true, message: "任务名称不能为空", trigger: "blur" }],
    type: [{ required: true, message: "任务类型不能为空", trigger: "blur" }],
    product: [{ required: true, message: "所属产品不能为空", trigger: "blur" }],
    nodes: [{ required: true, message: "执行节点不能为空", trigger: "blur" }],
    env: [{ required: true, message: "测试环境不能为空", trigger: "blur" }],
    tcs: [{ required: true, message: "执行用例不能为空", trigger: "blur" }],
    owner: [{ required: true, message: "负责人不能为空", trigger: "blur" }],
    plugin: [
      {
        required: computed(() => form.value.level === "1"),
        message: "执行插件不能为空",
        trigger: "blur",
      },
    ],
  },
});

const { queryParams, form, rules } = toRefs(data);

const props = defineProps({
  id: { type: String, default: "" },
  operate: { type: String, default: "add" },
  getMethod: { type: Function, default: undefined },
  addMethod: { type: Function, default: undefined },
  updateMethod: { type: Function, default: undefined },
});

/** 切换手动/自动化测试任务 */
function handleTypeChange(val) {
  automate.value = val === "1" ? true : false;
}

/** 执行级别为用例级时，执行策略自动切换为并发模块 */
function handleLevelChange(val) {
  if (val === "0") {
    form.value.policy = "0";
  }
}

/** 选中所属产品变更事件 */
function changeProductOptions(val) {
  queryParams.value.product = val;
  treeselect(queryParams.value).then((response) => {
    caseOptions.value = response.data;
  });
}

/** 选中计划信息变更事件 */
function changeTestPlanOptions(val) {
  console.log("选中计划信息变更事件");
}

/** cron表达式按钮操作 */
function handleShowCron() {
  expression.value = form.value.cron;
  openCron.value = true;
}

/** 确定后回传值 */
function submitCronTab(value) {
  form.value.cron = value;
}

/** 获取树节点及其选中状态 */
function getTreeNodes(treeNodes, checkedKeys) {
  treeNodes(queryParams.value).then((response) => {
    caseOptions.value = response.data;
    checkedKeys.forEach((v) => {
      nextTick(() => {
        caseRef.value.setChecked(v.value, true, true);
      });
    });
  });
}

/** 打开对话框事件 */
function open() {
  switch (props.operate) {
    case "update":
      props.getMethod(props.id).then((res) => {
        form.value = res.data;
        nextTick(() => {
          handleTypeChange(form.value.type);
          queryParams.value.product = form.value.product.value;
          getTreeNodes(treeselect, form.value.tcs);
        });
      });
      break;
    default:
      reset();
      break;
  }
}

/** 重置Form方法 */
function reset() {
  handleTypeChange();
  handleCheckedTreeNodeAll();
  caseExpand.value = false;
  caseNodeAll.value = false;
  form.value = {
    tcs: [],
    type: "0",
    status: "0",
    policy: "0",
    level: "0",
    params: JSON.stringify(defaultParams.value),
  };
  proxy.resetForm("addRef");
}

/** 树权限（展开/折叠）*/
function handleCheckedTreeExpand(value) {
  let treeList = caseOptions.value;
  for (let i = 0; i < treeList.length; i++) {
    caseRef.value.store.nodesMap[treeList[i].id].expanded = value;
  }
}

/** 任务插件列表查询 */
function handleJobPlugins() {
  router.push({
    path: "/tms/job-plugin/index",
  });
}

/** 树权限（全选/全不选） */
function handleCheckedTreeNodeAll(value) {
  caseRef.value.setCheckedNodes(value ? caseOptions.value : []);
}

/** 树权限（父子联动） */
function handleCheckedTreeConnect(value) {
  caseCheckStrictly.value != true;
}

/** 所有用例节点数据 */
function getCaseAllCheckedKeys() {
  // 目前被选中的用例节点
  let checkedKeys = [];
  let checkedNodes = caseRef.value.getCheckedNodes();

  checkedNodes.forEach(function (node) {
    if (node.type == "TestCase") {
      checkedKeys.push(node.id);
    }
  });

  // 半选中的用例节点
  let halfCheckedKeys = [];
  let halfCheckedNodes = caseRef.value.getHalfCheckedNodes();
  halfCheckedNodes.forEach(function (node) {
    if (node.type == "TestCase") {
      halfCheckedKeys.push(node.id);
    }
  });
  checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys);
  return checkedKeys;
}

/** 提交按钮事件 */
function submit() {
  form.value.tcs = getCaseAllCheckedKeys();
  proxy.$refs.addRef.validate((valid) => {
    if (valid) {
      if (form.value.id != undefined) {
        props.updateMethod(form.value).then((res) => {
          proxy.$modal.msgSuccess("修改成功");
          submited();
        });
      } else {
        props.addMethod(form.value).then((res) => {
          proxy.$modal.msgSuccess("新增成功");
          submited();
        });
      }
    }
  });
}

/** submited事件 */
function submited() {
  emit("submited");
  emit("close");
}
</script>
